import ttkbootstrap as ttkb
from ttkbootstrap.constants import *
from tkinter import messagebox, StringVar, IntVar, BooleanVar
from datetime import datetime, date, timedelta
from data_manager.db_handler import get_tasks_by_project

class BaseDialog(ttkb.Toplevel):
    """基础对话框：Windows 居中+模态+表单校验"""
    def __init__(self, parent, title="对话框", width=500, height=400):
        super().__init__(parent)
        self.parent = parent
        self.title(title)
        self.geometry(f"{width}x{height}")
        self.resizable(False, False)  # Windows 禁止缩放（避免布局错乱）
        self.result = None  # 存储返回结果
        self._center_window()  # Windows 窗口居中
        self.grab_set()  # 模态：阻止操作父窗口
        self._build_ui()

    def _center_window(self):
        """Windows 窗口居中（适配不同分辨率）"""
        self.update_idletasks()
        screen_width = self.winfo_screenwidth()
        screen_height = self.winfo_screenheight()
        win_width = self.winfo_width()
        win_height = self.winfo_height()
        # 计算居中坐标（避免贴边）
        x = max(0, (screen_width - win_width) // 2)
        y = max(0, (screen_height - win_height) // 2)
        self.geometry(f"+{x}+{y}")

    def _build_ui(self):
        """构建UI：子类重写"""
        pass

    def _validate_form(self):
        """表单校验：子类重写，返回 (是否有效, 错误信息)"""
        return True, ""

    def _on_confirm(self):
        """确认回调：校验通过后返回结果"""
        is_valid, err_msg = self._validate_form()
        if not is_valid:
            messagebox.showerror("表单错误", err_msg, parent=self)
            return
        self.destroy()

    def _on_cancel(self):
        """取消回调：清空结果"""
        self.result = None
        self.destroy()


class ProjectFormDialog(BaseDialog):
    """项目表单：新建/编辑（修复 TypeError：action 子类单独处理）"""
    def __init__(self, parent, title, action="create", init_data=None):
        self.action = action  # "create"/"edit"（不传给 BaseDialog）
        self.init_data = init_data or {}  # 编辑时的初始数据
        # 调用父类时不传递 action（避免 TypeError）
        super().__init__(parent, title=title, width=750, height=450)  # 大幅增大窗口尺寸

    def _build_ui(self):
        """Windows 风格表单：项目名称/日期/描述"""
        form_frame = ttkb.Frame(self, padding=(20, 20))
        form_frame.pack(fill=BOTH, expand=YES)

        # 1. 项目名称（必填）
        name_label = ttkb.Label(form_frame, text="项目名称 *")
        name_label.grid(row=0, column=0, sticky=W, pady=(0, 5))
        
        self.name_var = StringVar(value=self.init_data.get("name", ""))
        name_entry = ttkb.Entry(
            form_frame, textvariable=self.name_var, width=40
        )
        name_entry.grid(row=0, column=1, columnspan=2, sticky=W, pady=(0, 10))
        name_entry.focus()  # Windows 默认聚焦到必填项

        # 2. 开始日期（必填，Windows 日期选择器）
        start_label = ttkb.Label(form_frame, text="开始日期 *")
        start_label.grid(row=1, column=0, sticky=W, pady=(0, 5))
        
        default_start_str = self.init_data.get("start_date", date.today().strftime("%Y-%m-%d"))
        self.start_var = StringVar(value=default_start_str)
        start_entry = ttkb.DateEntry(
            form_frame, dateformat="%Y-%m-%d",
            width=18, bootstyle=PRIMARY
        )
        # 将日期字符串转换为datetime对象
        default_start = datetime.strptime(default_start_str, "%Y-%m-%d").date()
        start_entry.set_date(default_start)
        start_entry.grid(row=1, column=1, sticky=W, pady=(0, 10))

        # 3. 计划结束日期（必填）
        end_label = ttkb.Label(form_frame, text="计划结束日期 *")
        end_label.grid(row=1, column=2, sticky=W, padx=(20, 0), pady=(0, 5))
        
        # 新建时默认 7 天后，编辑时用初始值
        default_end_str = self.init_data.get(
            "end_date", (date.today() + timedelta(days=7)).strftime("%Y-%m-%d")
        )
        self.end_var = StringVar(value=default_end_str)
        end_entry = ttkb.DateEntry(
            form_frame, dateformat="%Y-%m-%d",
            width=18, bootstyle=PRIMARY
        )
        # 将日期字符串转换为datetime对象
        default_end = datetime.strptime(default_end_str, "%Y-%m-%d").date()
        end_entry.set_date(default_end)
        end_entry.grid(row=1, column=3, sticky=W, pady=(0, 10))

        # 4. 项目描述（可选）
        desc_label = ttkb.Label(form_frame, text="项目描述")
        desc_label.grid(row=2, column=0, sticky=W, pady=(0, 5))
        
        self.desc_text = ttkb.Text(
            form_frame, width=60, height=8
        )
        # 填充初始描述
        if "description" in self.init_data:
            self.desc_text.insert(1.0, self.init_data["description"])
        self.desc_text.grid(row=3, column=0, columnspan=4, sticky=W+E, pady=(0, 15))

        # 5. 按钮区（Windows 风格：确认/取消）
        btn_frame = ttkb.Frame(form_frame)
        btn_frame.grid(row=4, column=0, columnspan=4, pady=(10, 0))
        
        confirm_btn = ttkb.Button(
            btn_frame, text="确认", command=self._on_confirm,
            bootstyle=SUCCESS, width=12
        )
        confirm_btn.pack(side=LEFT, padx=(0, 15))
        
        cancel_btn = ttkb.Button(
            btn_frame, text="取消", command=self._on_cancel,
            bootstyle=OUTLINE, width=12
        )
        cancel_btn.pack(side=LEFT)

    def _validate_form(self):
        """Windows 表单校验：必填项+日期逻辑"""
        # 1. 必填项检查
        name = self.name_var.get().strip()
        start_date = self.start_var.get().strip()
        end_date = self.end_var.get().strip()
        
        if not name:
            return False, "项目名称不能为空"
        if not start_date:
            return False, "开始日期不能为空"
        if not end_date:
            return False, "计划结束日期不能为空"
        
        # 2. 日期逻辑（开始 <= 结束）
        try:
            start = datetime.strptime(start_date, "%Y-%m-%d")
            end = datetime.strptime(end_date, "%Y-%m-%d")
            if start > end:
                return False, "开始日期不能晚于计划结束日期"
        except ValueError:
            return False, "日期格式错误，请通过选择器选择"
        
        return True, ""

    def _on_confirm(self):
        """组装项目结果（含描述）"""
        self.result = {
            "name": self.name_var.get().strip(),
            "start_date": self.start_var.get().strip(),
            "end_date": self.end_var.get().strip(),
            "description": self.desc_text.get(1.0, ttkb.END).strip()  # 去除末尾换行
        }
        super()._on_confirm()


class TaskFormDialog(BaseDialog):
    """任务表单：新建/编辑（Windows 层级适配+依赖任务）"""
    def __init__(self, parent, title, action="create", init_data=None):
        self.action = action
        self.init_data = init_data or {}
        # 获取当前项目ID（Windows 父窗口层级：task_panel -> left_vertical_pane -> horizontal_pane -> main）
        self.project_id = parent.master.master.current_project_id if (
            hasattr(parent, "master") and hasattr(parent.master, "master") and 
            hasattr(parent.master.master, "current_project_id")
        ) else None
        super().__init__(parent, title=title, width=850, height=650)  # 大幅增大窗口尺寸

    def _build_ui(self):
        """Windows 任务表单：多字段+依赖选择"""
        form_frame = ttkb.Frame(self, padding=(20, 20))
        form_frame.pack(fill=BOTH, expand=YES)

        # 1. 任务名称（必填）
        name_label = ttkb.Label(form_frame, text="任务名称 *")
        name_label.grid(row=0, column=0, sticky=W, pady=(0, 5))
        
        self.name_var = StringVar(value=self.init_data.get("task_name", ""))
        name_entry = ttkb.Entry(
            form_frame, textvariable=self.name_var, width=50
        )
        name_entry.grid(row=0, column=1, columnspan=3, sticky=W, pady=(0, 10))
        name_entry.focus()

        # 2. 优先级（必填）
        priority_label = ttkb.Label(form_frame, text="优先级 *")
        priority_label.grid(row=1, column=0, sticky=W, pady=(0, 5))
        
        self.priority_var = StringVar(value=self.init_data.get("priority", "中"))
        priority_combo = ttkb.Combobox(
            form_frame, textvariable=self.priority_var,
            values=["高", "中", "低"], state="readonly", width=12
        )
        priority_combo.grid(row=1, column=1, sticky=W, pady=(0, 10))

        # 3. 负责人（必填）
        owner_label = ttkb.Label(form_frame, text="负责人 *")
        owner_label.grid(row=1, column=2, sticky=W, padx=(20, 0), pady=(0, 5))
        
        self.owner_var = StringVar(value=self.init_data.get("owner", "未指定"))
        owner_entry = ttkb.Entry(
            form_frame, textvariable=self.owner_var, width=25
        )
        owner_entry.grid(row=1, column=3, sticky=W, pady=(0, 10))

        # 4. 开始/结束日期（必填）
        start_label = ttkb.Label(form_frame, text="开始日期 *")
        start_label.grid(row=2, column=0, sticky=W, pady=(0, 5))
        
        default_start_str = self.init_data.get("start_date", date.today().strftime("%Y-%m-%d"))
        self.start_var = StringVar(value=default_start_str)
        start_entry = ttkb.DateEntry(
            form_frame, dateformat="%Y-%m-%d",
            width=18, bootstyle=PRIMARY
        )
        # 将日期字符串转换为datetime对象
        default_start = datetime.strptime(default_start_str, "%Y-%m-%d").date()
        start_entry.set_date(default_start)
        start_entry.grid(row=2, column=1, sticky=W, pady=(0, 10))

        end_label = ttkb.Label(form_frame, text="计划结束日期 *")
        end_label.grid(row=2, column=2, sticky=W, padx=(20, 0), pady=(0, 5))
        
        default_end_str = self.init_data.get(
            "end_date", (date.today() + timedelta(days=3)).strftime("%Y-%m-%d")
        )
        self.end_var = StringVar(value=default_end_str)
        end_entry = ttkb.DateEntry(
            form_frame, dateformat="%Y-%m-%d",
            width=18, bootstyle=PRIMARY
        )
        # 将日期字符串转换为datetime对象
        default_end = datetime.strptime(default_end_str, "%Y-%m-%d").date()
        end_entry.set_date(default_end)
        end_entry.grid(row=2, column=3, sticky=W, pady=(0, 10))

        # 5. 任务状态（必填）
        status_label = ttkb.Label(form_frame, text="任务状态 *")
        status_label.grid(row=3, column=0, sticky=W, pady=(0, 5))
        
        self.status_var = StringVar(value=self.init_data.get("status", "未开始"))
        status_combo = ttkb.Combobox(
            form_frame, textvariable=self.status_var,
            values=["未开始", "进行中", "已完成", "延期"], state="readonly", width=12
        )
        status_combo.grid(row=3, column=1, sticky=W, pady=(0, 10))

        # 6. 完成进度（必填，0-100）
        progress_label = ttkb.Label(form_frame, text="完成进度(%) *")
        progress_label.grid(row=3, column=2, sticky=W, padx=(20, 0), pady=(0, 5))
        
        self.progress_var = IntVar(value=self.init_data.get("progress", 0))
        progress_scale = ttkb.Scale(
            form_frame, variable=self.progress_var, from_=0, to=100,
            orient=HORIZONTAL, length=200, bootstyle=SUCCESS
        )
        progress_scale.grid(row=3, column=3, sticky=W, pady=(0, 10))
        # 进度数值显示
        self.progress_label = ttkb.Label(
            form_frame, textvariable=self.progress_var
        )
        self.progress_label.grid(row=3, column=4, sticky=W, padx=(10, 0))

        # 7. 依赖任务（可选，当前项目的其他任务）
        dep_label = ttkb.Label(form_frame, text="依赖任务")
        dep_label.grid(row=4, column=0, sticky=W, pady=(0, 5))
        
        self.dep_var = StringVar(value=self.init_data.get("dependency", "无依赖"))
        dep_tasks = ["无依赖"]
        # 仅当项目ID有效时，加载依赖任务
        if self.project_id and self.project_id != "None":
            tasks = get_tasks_by_project(int(self.project_id))  # ID 转整数
            current_task_id = self.init_data.get("task_id")  # 编辑时排除自身
            for task in tasks:
                task_id, task_name = task[0], task[1]
                if self.action == "edit" and task_id == current_task_id:
                    continue
                dep_tasks.append(f"{task_id}-{task_name}")
        
        dep_combo = ttkb.Combobox(
            form_frame, textvariable=self.dep_var, values=dep_tasks,
            state="readonly", width=45
        )
        dep_combo.grid(row=4, column=1, columnspan=3, sticky=W, pady=(0, 10))

        # 8. 任务描述（可选）
        desc_label = ttkb.Label(form_frame, text="任务描述")
        desc_label.grid(row=5, column=0, sticky=W, pady=(0, 5))
        
        self.desc_text = ttkb.Text(
            form_frame, width=75, height=6
        )
        if "description" in self.init_data:
            self.desc_text.insert(1.0, self.init_data["description"])
        self.desc_text.grid(row=6, column=0, columnspan=5, sticky=W+E, pady=(0, 15))

        # 9. 按钮区
        btn_frame = ttkb.Frame(form_frame)
        btn_frame.grid(row=7, column=0, columnspan=5, pady=(10, 0))
        
        confirm_btn = ttkb.Button(
            btn_frame, text="确认", command=self._on_confirm,
            bootstyle=SUCCESS, width=12
        )
        confirm_btn.pack(side=LEFT, padx=(0, 15))
        
        cancel_btn = ttkb.Button(
            btn_frame, text="取消", command=self._on_cancel,
            bootstyle=OUTLINE, width=12
        )
        cancel_btn.pack(side=LEFT)

    def _validate_form(self):
        """任务表单校验：Windows 业务逻辑适配"""
        # 1. 必填项检查
        name = self.name_var.get().strip()
        priority = self.priority_var.get()
        owner = self.owner_var.get().strip()
        start_date = self.start_var.get().strip()
        end_date = self.end_var.get().strip()
        status = self.status_var.get()
        progress = self.progress_var.get()
        
        if not name:
            return False, "任务名称不能为空"
        if not priority:
            return False, "请选择优先级"
        if not owner:
            return False, "负责人不能为空"
        if not start_date or not end_date:
            return False, "日期不能为空，请通过选择器选择"
        
        # 2. 日期逻辑
        try:
            start = datetime.strptime(start_date, "%Y-%m-%d")
            end = datetime.strptime(end_date, "%Y-%m-%d")
            if start > end:
                return False, "开始日期不能晚于计划结束日期"
        except ValueError:
            return False, "日期格式错误（需为 YYYY-MM-DD）"
        
        # 3. 进度逻辑（已完成必须100%，未开始/延期必须0%）
        if status == "已完成" and progress != 100:
            return False, "「已完成」状态的任务进度必须为100%"
        if status in ["未开始", "延期"] and progress > 0:
            return False, "「未开始」或「延期」状态的任务进度不能大于0%"
        
        return True, ""

    def _on_confirm(self):
        """组装任务结果并调用父类确认方法"""
        self.result = {
            "task_name": self.name_var.get().strip(),
            "priority": self.priority_var.get(),
            "owner": self.owner_var.get().strip(),
            "start_date": self.start_var.get().strip(),
            "end_date": self.end_var.get().strip(),
            "status": self.status_var.get(),
            "progress": self.progress_var.get(),
            "description": self.desc_text.get(1.0, ttkb.END).strip(),
            "dependency": self.dep_var.get()
        }
        super()._on_confirm()


class BatchTaskDialog(BaseDialog):
    """批量任务修改：Windows 简化表单"""
    def __init__(self, parent, title):
        super().__init__(parent, title=title, width=450, height=300)

    def _build_ui(self):
        """批量修改表单：仅保留可批量更新的字段"""
        form_frame = ttkb.Frame(self, padding=(20, 20))
        form_frame.pack(fill=BOTH, expand=YES)

        # 1. 优先级（可选修改）
        priority_label = ttkb.Label(form_frame, text="优先级（可选）")
        priority_label.grid(row=0, column=0, sticky=W, pady=(0, 5))
        
        self.priority_var = StringVar(value="不修改")
        priority_combo = ttkb.Combobox(
            form_frame, textvariable=self.priority_var,
            values=["不修改", "高", "中", "低"], state="readonly", width=15
        )
        priority_combo.grid(row=0, column=1, sticky=W, pady=(0, 15))

        # 2. 任务状态（可选修改）
        status_label = ttkb.Label(form_frame, text="任务状态（可选）")
        status_label.grid(row=1, column=0, sticky=W, pady=(0, 5))
        
        self.status_var = StringVar(value="不修改")
        status_combo = ttkb.Combobox(
            form_frame, textvariable=self.status_var,
            values=["不修改", "未开始", "进行中", "已完成", "延期"], state="readonly", width=15
        )
        status_combo.grid(row=1, column=1, sticky=W, pady=(0, 15))

        # 3. 负责人（可选修改）
        owner_label = ttkb.Label(form_frame, text="负责人（可选）")
        owner_label.grid(row=2, column=0, sticky=W, pady=(0, 5))
        
        self.owner_var = StringVar(value="不修改")
        owner_entry = ttkb.Entry(
            form_frame, textvariable=self.owner_var, width=25
        )
        owner_entry.grid(row=2, column=1, sticky=W, pady=(0, 15))

        # 4. 完成进度（可选修改，-1=不修改）
        progress_label = ttkb.Label(form_frame, text="完成进度(%)（可选）")
        progress_label.grid(row=3, column=0, sticky=W, pady=(0, 5))
        
        self.progress_var = IntVar(value=-1)
        progress_scale = ttkb.Scale(
            form_frame, variable=self.progress_var, from_=-1, to=100,
            orient=HORIZONTAL, length=200, bootstyle=SUCCESS
        )
        progress_scale.set(-1)  # 默认不修改
        progress_scale.grid(row=3, column=1, sticky=W, pady=(0, 15))
        # 进度提示文本（-1 显示“不修改”）
        self.progress_text = ttkb.Label(form_frame, text="不修改")
        self.progress_text.grid(row=3, column=2, sticky=W, padx=(10, 0))
        # 绑定进度变化事件
        self.progress_var.trace_add("write", self._update_progress_text)

        # 5. 按钮区
        btn_frame = ttkb.Frame(form_frame)
        btn_frame.grid(row=4, column=0, columnspan=3, pady=(20, 0))
        
        confirm_btn = ttkb.Button(
            btn_frame, text="确认修改", command=self._on_confirm,
            bootstyle=SUCCESS, width=12
        )
        confirm_btn.pack(side=LEFT, padx=(0, 15))
        
        cancel_btn = ttkb.Button(
            btn_frame, text="取消", command=self._on_cancel,
            bootstyle=OUTLINE, width=12
        )
        cancel_btn.pack(side=LEFT)

    def _update_progress_text(self, *args):
        """Windows 进度提示更新：-1=不修改，其他显示百分比"""
        val = self.progress_var.get()
        if val == -1:
            self.progress_text.config(text="不修改")
        else:
            self.progress_text.config(text=f"{val}%")

    def _validate_form(self):
        """批量修改校验：至少选择一个字段"""
        has_change = False
        # 检查优先级
        if self.priority_var.get() != "不修改":
            has_change = True
        # 检查状态
        if self.status_var.get() != "不修改":
            has_change = True
        # 检查负责人（非“不修改”且非空）
        owner = self.owner_var.get().strip()
        if owner and owner != "不修改":
            has_change = True
        # 检查进度（非-1）
        if self.progress_var.get() != -1:
            has_change = True
        
        if not has_change:
            return False, "请至少选择一个需要修改的字段"
        
        # 进度逻辑提示（非强制，仅警告）
        if self.status_var.get() == "已完成" and self.progress_var.get() != 100 and self.progress_var.get() != -1:
            messagebox.showwarning("提示", "「已完成」状态建议将进度设为100%", parent=self)
        
        return True, ""

    def _on_confirm(self):
        """组装批量修改结果（过滤“不修改”字段）"""
        self.result = {}
        # 优先级
        priority = self.priority_var.get()
        if priority != "不修改":
            self.result["priority"] = priority
        # 状态
        status = self.status_var.get()
        if status != "不修改":
            self.result["status"] = status
        # 负责人
        owner = self.owner_var.get().strip()
        if owner and owner != "不修改":
            self.result["owner"] = owner
        # 进度
        progress = self.progress_var.get()
        if progress != -1:
            self.result["progress"] = progress
        
        super()._on_confirm()
